package me.zhengjie.minbearwcs.serivce.common;

import lombok.extern.slf4j.Slf4j;
import me.zhengjie.minbearwcs.dao.storage.inf.LargeStorageDao;
import me.zhengjie.minbearwcs.dao.storage.inf.MediumStorageDao;
import me.zhengjie.minbearwcs.dao.storage.inf.SmallStorageDao;
import me.zhengjie.minbearwcs.entity.DTO.common.ExcelInfo;
import me.zhengjie.minbearwcs.entity.DTO.transfer.Tuple;
import me.zhengjie.minbearwcs.entity.PO.wcs.storage.LargeStorage;
import me.zhengjie.minbearwcs.entity.PO.wcs.storage.MediumStorage;
import me.zhengjie.minbearwcs.entity.PO.wcs.storage.SmallStorage;
import me.zhengjie.minbearwcs.entity.PO.wcs.storage.type.StorageType;
import org.apache.poi.ss.usermodel.*;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Paths;
import java.util.*;

@Slf4j
@Service
public class MinBearUploadService {

    private final LargeStorageDao largeStorageDao;
    private final MediumStorageDao mediumStorageDao;
    private final SmallStorageDao smallStorageDao;
    private final Map<String, StorageType> storageTypeMap = new HashMap<>();

    private final ResourceLoader resourceLoader;


    public MinBearUploadService(LargeStorageDao largeStorageDao, MediumStorageDao mediumStorageDao, SmallStorageDao smallStorageDao, ResourceLoader resourceLoader) {
        this.largeStorageDao = largeStorageDao;
        this.mediumStorageDao = mediumStorageDao;
        this.smallStorageDao = smallStorageDao;
        this.resourceLoader = resourceLoader;

        for (StorageType type : StorageType.values()) {
            storageTypeMap.put(type.getStorageName(), type);
        }
    }


    @Transactional
    public Tuple<String> importExcelData(Workbook workbook) {
        largeStorageDao.clear();
        mediumStorageDao.clear();
        smallStorageDao.clear();

        Sheet sheet = workbook.getSheetAt(0);
//        Iterator<Row> rowIterator = sheet.rowIterator();

        int LARGE_STORAGE = 0;
        int FLOOR_NUM = 0;
        int LARGE_STORAGE_TYPE = 0;
        int LARGE_STORAGE_ORDER = 0;
        int MEDIUM_STORAGE = 0;
        int MEDIUM_STORAGE_ORDER = 0;
        int SMALL_STORAGE = 0;
        int SMALL_STORAGE_ORDER = 0;
        int IS_ENTER = 0;
        int QR_POINT = 0;
        int STORAGE_LENGTH = 0;
        int STORAGE_WIDTH = 0;

        int HEAD_ROW = 0;


        ExcelInfo first = findHeadIndex(sheet, "大储位号");
        HEAD_ROW = first.getRowNum();
        LARGE_STORAGE = first.getColumnNum();
        FLOOR_NUM = findHeadIndex(sheet, "楼层").getColumnNum();
        LARGE_STORAGE_TYPE = findHeadIndex(sheet, "大储位类型").getColumnNum();
        LARGE_STORAGE_ORDER = findHeadIndex(sheet, "大储位序号").getColumnNum();
        MEDIUM_STORAGE = findHeadIndex(sheet, "中储位号").getColumnNum();
        MEDIUM_STORAGE_ORDER = findHeadIndex(sheet, "中储位序号").getColumnNum();
        SMALL_STORAGE = findHeadIndex(sheet, "小储位号").getColumnNum();
        SMALL_STORAGE_ORDER = findHeadIndex(sheet, "小储位序号").getColumnNum();
        IS_ENTER = findHeadIndex(sheet, "是否中储位入口").getColumnNum();
        QR_POINT = findHeadIndex(sheet, "地标码").getColumnNum();
        STORAGE_LENGTH = findHeadIndex(sheet, "储位长度").getColumnNum();
        STORAGE_WIDTH = findHeadIndex(sheet, "储位宽度").getColumnNum();


        // 循环行Row
        for (int rowNum = HEAD_ROW + 1; rowNum <= sheet.getLastRowNum(); rowNum++) {
            Row hssfRow = sheet.getRow(rowNum);
            if (hssfRow != null) {
                // 大储位
                Cell cellLarge = hssfRow.getCell(LARGE_STORAGE);
                if (getCellValue(cellLarge) == null) break;

                LargeStorage largeStorage = largeStorageDao.selectByLargeStorageCode(getCellValue(cellLarge));
                if (largeStorage == null) {
                    largeStorageDao.insert(
                            new LargeStorage(
                                    null,
                                    getCellValue(hssfRow.getCell(LARGE_STORAGE)),
                                    Integer.valueOf(getCellValue(hssfRow.getCell(FLOOR_NUM))),
                                    storageTypeMap.get(getCellValue(hssfRow.getCell(LARGE_STORAGE_TYPE))),
                                    Integer.valueOf(getCellValue(hssfRow.getCell(LARGE_STORAGE_ORDER))),
                                    null
                            )
                    );
                }

                // 中储位
                Cell cellMedium = hssfRow.getCell(MEDIUM_STORAGE);
                MediumStorage mediumStorage = mediumStorageDao.selectByMediumStorage(getCellValue(cellMedium));
                if (mediumStorage == null) {
                    mediumStorageDao.insert(
                            new MediumStorage(
                                    null,
                                    getCellValue(hssfRow.getCell(MEDIUM_STORAGE)),
                                    getCellValue(hssfRow.getCell(LARGE_STORAGE)),
                                    Integer.valueOf(getCellValue(hssfRow.getCell(MEDIUM_STORAGE_ORDER))),
                                    null, null, null, null, null, null, null
                            )
                    );
                }

                // 小储位
                Cell cellSmall = hssfRow.getCell(SMALL_STORAGE);
                SmallStorage smallStorage = smallStorageDao.selectBySmallStorage(getCellValue(cellSmall));
                if (smallStorage != null) {
                    log.error("小储位 {} ，重复插入", getCellValue(cellSmall));
                }

                String isEnterStr = getCellValue(hssfRow.getCell(IS_ENTER));
                int isEnter = 0;
                if ("是".equals(isEnterStr)) {
                    isEnter = 1;
                }

                smallStorageDao.insert(
                        new SmallStorage(
                                null,
                                getCellValue(hssfRow.getCell(SMALL_STORAGE)),
                                getCellValue(hssfRow.getCell(MEDIUM_STORAGE)),
                                Integer.valueOf(getCellValue(hssfRow.getCell(MEDIUM_STORAGE_ORDER))),
                                Integer.valueOf(getCellValue(hssfRow.getCell(SMALL_STORAGE_ORDER))),
                                isEnter,
                                null,
                                getCellValue(hssfRow.getCell(QR_POINT)),
                                Double.valueOf(getCellValue(hssfRow.getCell(STORAGE_LENGTH))),
                                Double.valueOf(getCellValue(hssfRow.getCell(STORAGE_WIDTH))),
                                null,
                                null

                        )
                );

            }
        }


        return Tuple.tuple(null, true);

    }


    private String getCellValue(Cell cell) {
        CellType cellType = null;
        try {
            cellType = cell.getCellType();
        } catch (Exception e) {
            log.error("Excel存在空白行", e);
            return null;
        }
        String cellValue = "";
        switch (cellType) {
            case STRING:
                cellValue = cell.getStringCellValue();
                break;
            case NUMERIC:
                cellValue = (int) cell.getNumericCellValue() + "";
                break;
            default:
                cellValue = "0";
        }
        return cellValue;
    }


    private ExcelInfo findHeadIndex(Sheet sheet, String targetValue) {
        for (Row row : sheet) { // 遍历工作表中的所有行
            int rowIndex = row.getRowNum(); // 获取当前行的行号（从0开始）
            for (Cell cell : row) { // 遍历当前行中的所有单元格
                if (cell.getCellType() == CellType.STRING && cell.getStringCellValue().equals(targetValue)) {
                    // 如果找到了目标值
                    int colIndex = cell.getColumnIndex(); // 获取当前单元格的列号（从0开始）
                    // 注意：Excel 中的行和列通常是从1开始计数的，所以这里加了1
                    return new ExcelInfo(rowIndex, colIndex);
                }
            }
        }
        return null;
    }


    public void exportLogModel(HttpServletResponse response, String logType) {
        String fileName = logType + "/log.log";
        String filePrefix = "log/";

        BufferedInputStream bufferedInputStream = null;
        BufferedOutputStream bufferedOutputStream = null;
        try {
            bufferedInputStream = new BufferedInputStream(new FileInputStream("./" + filePrefix + fileName));
            bufferedOutputStream = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream;charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            response.addHeader("Pargam", "no-cache");
            response.addHeader("Cache-Control", "no-cache");

            int len;
            byte[] bytes = new byte[1024];
            while ((len = bufferedInputStream.read(bytes)) != -1) {
                bufferedOutputStream.write(bytes, 0, len);
            }

            bufferedOutputStream.flush();
        } catch (Exception e) {
            log.error("下载log出错", e);
        } finally {
            try {
                assert bufferedInputStream != null;
                bufferedInputStream.close();
                assert bufferedOutputStream != null;
                bufferedOutputStream.close();
            } catch (Exception e) {
                log.error("下载log出错", e);
            }
        }

    }

    public void uploadJavaPackage(MultipartFile file) {
        if (file.isEmpty()) {
            return;
        }

        try {
//            String path = this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath();


            // 创建一个新文件，这将在服务器文件系统中创建该文件
            File dest = new File("upload/" + file.getOriginalFilename());


            // 确保目录存在
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }


            // 将文件保存到服务器
            file.transferTo(Paths.get(dest.getAbsolutePath()));


        } catch (IOException e) {
            log.error("文件上传错误", e);

        }
    }



    public void exportStorageTemplate(HttpServletResponse response) {
        String fileName = "storageTemplate.xlsx";
        String filePrefix = "storageTemplate/";

        BufferedInputStream bufferedInputStream = null;
        BufferedOutputStream bufferedOutputStream = null;
        try {
            bufferedInputStream = new BufferedInputStream(Objects.requireNonNull(this.getClass().getClassLoader().getResourceAsStream(filePrefix + fileName)));
            bufferedOutputStream = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream;charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            response.addHeader("Pargam", "no-cache");
            response.addHeader("Cache-Control", "no-cache");

            int len;
            byte[] bytes = new byte[1024];
            while ((len = bufferedInputStream.read(bytes)) != -1){
                bufferedOutputStream.write(bytes,0,len);
            }

            bufferedOutputStream.flush();
        } catch (Exception e) {
            log.error("下载模版出错", e);
        }finally {
            try {
                assert bufferedInputStream != null;
                bufferedInputStream.close();
                assert bufferedOutputStream != null;
                bufferedOutputStream.close();
            }catch (Exception e){
                log.error("下载模版出错",e);
            }
        }

    }
}
